grammar SysY;

/*===-------------------------------------------===*/
/* Lexer rules                                     */
/*===-------------------------------------------===*/


fragment Decimal: [0-9];
fragment Octal: [0-7];
fragment Heximal: [0-9a-fA-F];
fragment NonZeroDecimal: [1-9];

fragment Point:'.';
fragment Sign: [+-];


fragment Hexadecimal_Digit_Sequenece: Heximal+; //十六进制常数
fragment Binary_Exponent_Part: [pP] Sign? Digit_Sequence; //二进制指数部分
fragment Hexadecimal_fraction_constant: (Hexadecimal_Digit_Sequenece? Point Hexadecimal_Digit_Sequenece)
                                        | (Hexadecimal_Digit_Sequenece Point);
fragment Digit_Sequence: Decimal+ ;//十进制常数。这块文档定义的可以出现0012这种情况 ，不想前面很多0可以如下定义：NonZeroDecimal Decimal*
fragment Exponent_Part: [eE] Sign? Digit_Sequence; //二进制指数部分
fragment Fractional_Constant: (Digit_Sequence? Point Digit_Sequence)
                                |(Digit_Sequence Point); //小数常数 1.2 , .2  , 3. 三种情况;
fragment Hexadecimal_prefix:('0x' | '0X'); //十六进制前缀

fragment Hexadecimal_Floating_constant: (Hexadecimal_prefix Hexadecimal_fraction_constant Binary_Exponent_Part)
                                        |(Hexadecimal_prefix Hexadecimal_Digit_Sequenece Binary_Exponent_Part);
                                        //十六进制浮点常数 ,比如 ：oX14afp-3
fragment Decimal_Floating_constant: (Fractional_Constant Exponent_Part?)
                                    | (Digit_Sequence Exponent_Part);
                                    //十进制浮点常数，分成小数和整数两部分

IntConst: Decimal
        |NonZeroDecimal Decimal+
        | '0' Octal+
		| ('0x' | '0X') Heximal+;
FloatConst:Decimal_Floating_constant | Hexadecimal_Floating_constant; 
Comma: ',';

Semicolon: ';';
Const: 'const';
Int: 'int';
Float: 'float';
LeftSquareBracket: '[';
RightSquareBracket: ']';
Equal: '=';
LeftBrace: '{';
RightBrace: '}';
LeftParenthesis: '(';
RightParenthesis: ')';
Void: 'void';
If: 'if';
Else: 'else';
While: 'while';
Break: 'break';
Continue: 'continue';
Return: 'return';
Add: '+';
Minus: '-';
ExclamationPoint: '!';
Multiply: '*';
Divide: '/';
Mod: '%';
Less: '<';
More: '>';
LessEqual: '<=';
MoreEqual: '>=';
EqualEqual: '==';
NotEqual: '!=';
And: '&&';
Or: '||';

fragment ESC: '\\"' | '\\\\';

WS: [ \t\r\n] -> skip;

LINE_COMMENT: '//' .*? '\r'? '\n' -> skip;
COMMENT: '/*' .*? '*/' -> skip;

fragment Ident_nondigit: [a-zA-Z_];

Ident: Ident_nondigit [a-zA-Z_0-9]*; 


String: '"' (ESC | .)*? '"';


/*===-------------------------------------------===*/
/* Syntax rules                                    */
/*===-------------------------------------------===*/

compUnit: (decl | funcDef)+ EOF;
//把有关数组的内容去掉了
decl: constDecl | varDecl;
constDecl: Const bType constDef (Comma constDef)* Semicolon;
bType: Int | Float;
constDef: Ident (LeftSquareBracket constExp RightSquareBracket)* Equal constInitVal;
constInitVal: constExp;
varDecl: bType varDef(Comma varDef)* Semicolon;
varDef: Ident (Equal initVal)?;
initVal: exp ;
funcDef: funcType Ident LeftParenthesis (funcFParams)? RightParenthesis block;
funcType: Void | Int | Float;
funcFParams: funcFParam (Comma funcFParam)*;
funcFParam: bType Ident;
block: LeftBrace (blockItem)* RightBrace;
blockItem: decl | stmt;
assignStmt:lVal Equal exp Semicolon;
expStmt:(exp)? Semicolon; //把老师的emptyStmt和expStmt合并

ifStmt:If LeftParenthesis cond RightParenthesis stmt (Else stmt)?;
whileStmt:While LeftParenthesis cond RightParenthesis stmt;
breakStmt:Break Semicolon;
continueStmt:Continue Semicolon;
returnStmt:Return (exp)? Semicolon;
stmt:
	assignStmt
	| expStmt
	| ifStmt
	| whileStmt
	| breakStmt
	| continueStmt
	| returnStmt
	| block;

//增加call语句
exp: addExp | call;
call: Ident LeftParenthesis funcRParams? RightParenthesis;

cond: lOrExp;
//lVal: Ident (LeftSquareBracket exp RightSquareBracket)* 
//不带数组形式
lVal: Ident;
primaryExp: LeftParenthesis exp RightParenthesis | lVal | number;
number: IntConst | FloatConst;
unaryExp: primaryExp | Ident LeftParenthesis (funcRParams)? RightParenthesis 
                     | unaryOp unaryExp;
unaryOp: Add | Minus | ExclamationPoint;
funcRParams: exp (Comma exp)*;
mulExp: unaryExp | mulExp (Multiply | Divide | Mod) unaryExp;
addExp: mulExp | addExp (Add | Minus) mulExp;
relExp: addExp | relExp (More | Less | MoreEqual | LessEqual) addExp;
eqExp : relExp | eqExp (EqualEqual | NotEqual) relExp;
lAndExp: eqExp | lAndExp And eqExp;
lOrExp: lAndExp | lOrExp Or lAndExp;
constExp: addExp;